<template>
  <div class="demo-drawer__content" ref="componentsWrap">
    <el-form ref="componentFrom" :model="form" label-width="70px" :disabled="isDisabled">
      <el-form-item label="节点名称">
        <common-input v-model="form.name" placeholder="请输入"></common-input>
      </el-form-item>
      <el-form-item label="数据源">
        <el-select v-model="form.dataSourceId" :popper-append-to-body="false" placeholder="请选择" filterable clearable
          @change="handleChoose">
          <el-option v-for="(item, index) in newSourceList" :key="item.id" :value="item.id" :label="item.datasoureName"
            :disabled="item.status !== 0">
            <div style="float: left;width: calc(100% - 30px)">
              <span class="selectList">
                <common-carousel-text :content="item.datasoureName" :index="index" :fontSize="14">
                </common-carousel-text>
              </span>
            </div>
            <span v-if="item.status === 0" style="float: right; color: #67C23A; font-size: 13px">有效</span>
            <span v-else style="float: right; color: #F56C6C; font-size: 13px">无效</span>
          </el-option>
        </el-select>
      </el-form-item>
      <el-form-item label="查询语句" class="item-sql">
        <div style="display: flex;">
          <div class="code-editor-wrap" v-if="!isDisabled">
            <code-editor key="email-template-editor" v-model="form.sql" code="text/x-mysql" :variable="variable"
              placeholder="可输入变量(变量示例: &{userName}; 只支持英文状态的&符号，且字符类型和日期类型的变量需要加引号，如'&{updateTime}')，另注意：sql语句结尾请不要添加;(分号)。如果是字符条件，需要使用like语句，如like '%&{userName}%'">
            </code-editor>
          </div>
          <div v-else class="code-editor-wrap-disabled">{{ form.sql }}</div>
          <el-popover placement="right-start" width="200" trigger="click" ref="dataSetTableList"
            popper-class="data-set-table-list">
            <div class="d-s-t-l-wrap">
              <common-input v-model="searchVal" placeholder="查询表" prefix-icon="el-icon-search"></common-input>
              <div class="table-list" v-if="tableList.length"
                :style="{ '--theme-color': systemInfo.theme, '--theme-color-opacity': systemInfo.theme + '25' }">
                <div :class="['item', isClickIndex === index ? 'select-item' : '']" v-for="(item, index) in filterData"
                  :key="index" @click="handleClick(item, index)">
                  <common-carousel-text :content="item.name" :font-size="14">
                  </common-carousel-text>
                  <i class="el-icon-loading" v-if="isClickIndex === index && isLoading"></i>
                  <el-tooltip class="item" effect="dark" :content="errorMsg" placement="left"
                    v-else-if="isClickIndex === index && errorMsg">
                    <i class="el-icon-warning" style="color: #F56C6C"></i>
                  </el-tooltip>

                </div>
              </div>
              <div class="table-list tips" v-else v-loading="dataLoading">
                <span class="tip-content">暂无数据</span>
              </div>
            </div>
            <i slot="reference" class="el-icon-postcard" style="font-size: 20px; margin-left: 8px"></i>
          </el-popover>
        </div>

      </el-form-item>
    </el-form>
    <div class="errorMsg">
      <span>{{ msg }}</span>
      <span class="tips">
        注：使用变量时必须和关联字段类型一致，否则无法查询数据
      </span>
    </div>
  </div>
</template>

<script>
import {
  getTableByDataSouce,
  inputOutputFields,
  checkSql, querySourceList, getDataSourceList
} from '@/api/screenConfig/dataSet'
import CodeEditor from '@/components/CodeEditor'
import { _deepClone } from '@/utils'
import { mapGetters } from 'vuex'

export default {
  name: 'MysqlTableInput',
  components: {
    CodeEditor
  },
  props: {
    option: {
      type: Object,
      default: () => {
      }
    },
    // dataSourceList: {
    //   type: Array,
    //   default: () => []
    // },//数据源列表
    variable: {
      type: Array,
      default: () => []
    },//变量
    variableConfig: {
      type: Array,
      default: () => []
    },//变量配置
    isDisabled: {
      type: Boolean,
      default: () => false
    }//是否可编辑
  },
  data() {
    return {
      dataLoading: false,
      searchVal: '',
      form: {
        name: '',
        dataSourceId: '',
        tableName: '',
        sql: ''
      },
      isClickIndex: null,
      dataSourceId: '',
      tableList: [],
      msg: '',
      isLoading: false,
      errorMsg: null,
      newSourceList: []
      // variable: [],
    }
  },
  watch: {
    option: {
      handler: function (val, newVal) {
        this.getDataSourceList(val.dataSourceId)
        Reflect.ownKeys(this.form).forEach(k => this.form[k] = val[k])
        if (!this.tableList.length && val.dataSourceId) {
          this.getTableByDataSouce(this.form.dataSourceId)
        }
        if (val.dataSourceId && val.sql) {
          this.checkSql()
        }
      },
      deep: true,
      immediate: true
    },
    form: {
      handler: function (val, newVal) {
        let form = _deepClone(val)
        delete form.tableName
        let complete = Object.values(form).every(item => !!item)
        this.$emit('changeForm', val, complete)
      },
      deep: true
    },
    dataSourceId: {
      handler: function (val, newVal) {

      }
    }
  },
  computed: {
    ...mapGetters(['systemInfo']),
    getOption() {
      return this.option
    },
    filterData() {
      let list = []
      if (this.tableList.length) {
        if (this.searchVal) {
          list = this.tableList.filter(f => f.name.includes(this.searchVal))
        } else {
          list = this.tableList
        }
      }
      return list
    }
  },
  methods: {
    /**
     * 获取数据源列表信息
     */
    getDataSourceList(id) {
      let params = {
        status: 0,
        datasourceType: 'MYSQL'
      }
      if (id) params.id = id
      querySourceList(params).then((res) => {
        if (res && res.code === 200) {
          this.newSourceList = res.rows.reduce((r, c) => {
            if (c.datasourceType === 'MYSQL') {
              r.push(c)
            }
            return r
          }, [])
        } else {
          this.dataSourceList = []
        }
      })
    },
    // 选择数据源
    handleChoose(val) {
      this.getTableByDataSouce(this.form.dataSourceId)
      this.form.sql = ''
      this.tableList = []
    },
    // 根据id获取表数据
    getTableByDataSouce(id) {
      this.dataLoading = true
      getTableByDataSouce({ id }).then(res => {
        if (res && res.code === 200) {
          this.tableList = res.rows.reduce((r, c) => {
            r.push({
              name: c
            })
            return r
          }, [])
          if (!this.isClickIndex && this.form.tableName) {
            let index = this.tableList.findIndex(f => f.name === this.form.tableName)
            this.isClickIndex = index > -1 ? index : null
          }
        } else {
          this.tableList = []
        }
      }).finally(() => {
        this.dataLoading = false
      })
    },
    // 根据表数据获取表字段并且拼接sql查询语句
    handleClick(item, index) {
      if (this.isDisabled) return
      this.isClickIndex = index
      this.form.tableName = item.name
      this.dataLoading = true
      let params = {
        id: this.form.dataSourceId,
        mysqlParamVo: {
          tableName: item.name
        }
      }
      this.isLoading = true
      this.errorMsg = null
      inputOutputFields(params).then(res => {
        if (res && res.code === 200) {
          let fields = res.rows.reduce((r, c) => {
            r.push(c.fieldName)
            return r
          }, []).join(',')
          this.form.sql = `select ${fields} from ${item.name}`
          this.dataLoading = false
        } else {
          this.errorMsg = res.msg
        }
      }).catch(err => this.errorMsg = err.msg).finally(() => this.isLoading = false)
    },
    //重置
    resetForm(type) {
      if (type === 'MysqlTableInput') {
        this.form.dataSourceId = ''
        this.form.tableName = ''
        this.form.sql = ''
      }
    },
    //自定义校验方法
    checkFormBeforeClose() {
      if (this.form.sql) {
        let sql = this.form.sql.replace(/(^\s*)|(\s*$)/g, "");
        if (/update\s+|delete\s+|insert\s+|drop\s+|alter\s+|create\s+/.test(this.form.sql.toLowerCase())) {
          this.msg = '请输入正确的select查询语句'
          return
        } else if ([';', '；'].includes(sql[sql.length - 1])) {
          this.msg = 'sql语句错误，结尾请不要添加;(分号)，否则会执行失败'
          return
        }
        this.checkSql().then(res => {
          let complete = res.isTrue
          this.$emit('changeForm', this.form, complete, true)
          // if (!res.isTrue) this.$GlobalErrorConfirm('SQL检验失败', res.msg)
        })
        return 'ok'
      } else {
        this.msg = ''
        return 'ok'
      }
    },
    checkSql() {
      return new Promise((resolve, reject) => {
        // console.log(this.variableConfig)
        let params = {
          datasql: this.form.sql,
          datasourceId: this.form.dataSourceId,
          variableConfig: JSON.stringify(this.variableConfig)
        }
        checkSql(params).then(res => {
          let info = null
          if (res && res.code === 200 && res.msg === '查询语句正确!') {
            this.msg = ''
            info = {
              isTrue: true,
              msg: res.msg
            }
          } else if (res.code === 502) {
            this.msg = '数据源失效，sql语句检验失败'
            info = {
              isTrue: false,
              msg: res.msg
            }
          } else {
            this.msg = '检验sql查询语句错误'
            info = {
              isTrue: false,
              msg: res.msg
            }
          }
          resolve(info)
        })
      })
    }
  },
  mounted() {
    // Reflect.ownKeys(this.form).forEach(k => this.form[k] = this.option[k])
    // if (!this.tableList.length) {
    //   this.getTableByDataSouce(this.form.dataSourceId)
    // }
  }
}
</script>

<style scoped lang="scss">
.demo-drawer__content {
  padding: 0 16px 16px 16px;
  overflow-y: scroll;

  ul {
    list-style: none;
    padding: 0;
  }

  .el-icon-postcard {
    cursor: pointer;
  }

  .item-sql {}
}

.errorMsg {
  color: #F56C6C;
  font-size: 12px;
  position: relative;
  display: flex;
  flex-direction: column;
  margin-left: 70px;
  top: -14px;
}

::v-deep .el-select-dropdown {
  width: 220px;

  .selectList {
    height: 34px;
    display: flex;
    align-items: center;
    width: 100%;
    box-sizing: border-box;

    .carousel-text-warp {
      width: 100%;
    }
  }
}

.code-editor-wrap {
  width: calc(100% - 28px);
  height: 140px;
}

.code-editor-wrap-disabled {
  width: calc(100% - 28px);
  height: 140px;
  padding: 0 4px;
  background: #F5F7FA;
  color: #C0C4CC;
  border: 1px solid #DCDFE6;
  border-radius: 4px;
  cursor: not-allowed;
  word-wrap: break-word;
  overflow-y: scroll;
}
</style>
<style lang="scss">
.data-set-table-list {
  height: 240px;

  .d-s-t-l-wrap {
    width: 100%;
    height: 100%;
    display: flex;
    flex-direction: column;

    .table-list {
      margin-top: 8px;
      height: calc(100% - 40px);
      overflow-y: scroll;

      .item {
        padding: 2px 0;
        cursor: pointer;
        display: flex;
        align-items: center;

        &:hover {
          color: var(--theme-color);
          background-color: var(--theme-color-opacity);
        }

        .carousel-text-warp {
          width: calc(100% - 22px);
        }

        .el-icon-loading,
        .el-icon-warning {
          margin-left: 4px;
        }
      }

      .select-item {
        color: var(--theme-color);
        background-color: var(--theme-color-opacity);
      }
    }

    .tips {
      display: flex;
      align-items: center;
      justify-content: center;
      font-size: 12px;
    }
  }
}
</style>

